package com.examplemartin.jpademo.service.purin;

import com.examplemartin.jpademo.bean.AjaxResult;
import com.examplemartin.jpademo.dao.PurInDao;
import com.examplemartin.jpademo.pojo.po.good.GoodPO;
import com.examplemartin.jpademo.pojo.po.purchase.PurDetailPO;
import com.examplemartin.jpademo.pojo.po.purchase.PurPO;
import com.examplemartin.jpademo.pojo.po.repository.purchase.PurInDetailPO;
import com.examplemartin.jpademo.pojo.po.repository.purchase.PurInPO;
import com.examplemartin.jpademo.pojo.po.stock.RepoInfoPO;
import com.examplemartin.jpademo.pojo.po.stock.StockPO;
import com.examplemartin.jpademo.pojo.po.stock.SummGoodPO;
import com.examplemartin.jpademo.pojo.po.supplier.SupplierPO;
import com.examplemartin.jpademo.service.GoodService;
import com.examplemartin.jpademo.service.RepoInfoService;
import com.examplemartin.jpademo.service.pur.PurDetailService;
import com.examplemartin.jpademo.service.pur.PurchaseService;
import com.examplemartin.jpademo.service.stock.SummGoodService;
import com.examplemartin.jpademo.util.EntityCheckUtil;
import com.examplemartin.jpademo.util.UUIDUtile;
import com.examplemartin.jpademo.util.ValidateMember;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.*;
import java.util.*;

@Service
@Component
public class PurInService {


    public static Integer PURIN_STATUS_PRO_NO = 0;
    public static Integer PURIN_STATUS_ADMIN_NO = 1;
    public static Integer PURIN_STATUS_ABANDON_NO = 2;


    public static String PURIN_STATUS_PRO_NAME = "编制中";
    public static String PURIN_STATUS_ADMIN_NAME = "入库";
    public static String PURIN_STATUS_ABANDON_NAME = "废弃";

    public static HashMap<Integer, String> PURIN_STATUS_MAP = new HashMap<>();

    static {
        PURIN_STATUS_MAP.put(PURIN_STATUS_ABANDON_NO, PURIN_STATUS_ABANDON_NAME);
        PURIN_STATUS_MAP.put(PURIN_STATUS_PRO_NO, PURIN_STATUS_PRO_NAME);
        PURIN_STATUS_MAP.put(PURIN_STATUS_ADMIN_NO, PURIN_STATUS_ADMIN_NAME);
    }


    @Resource
    private PurInDao purInDao;

    @Resource
    private RepoInfoService repoInfoService;

    @Resource
    private PurInService purInService;

    @Resource
    private PurInDetailService purInDetailService;

    @Resource
    private PurchaseService purchaseService;

    @Resource
    private GoodService goodService;

    @Resource
    private PurDetailService purDetailService;
    @Resource
    private SummGoodService summGoodService;

    /**
     * 模糊查询 获取入库单
     */
    // 01 采购订单名 and 采购入库单名
    public List<PurInPO> findAll(String purname, String inname, Long supplierid, Integer statusId) {

        // 模糊查询
        // 模糊查询 01 sort
        Sort byPurName = Sort.by(Sort.Direction.ASC, "purPO.name");
        Sort bycreateTime = Sort.by(Sort.Direction.ASC, "createTime");
        Sort bystatus = Sort.by(Direction.ASC, "status");
        Sort and = byPurName.and(bycreateTime).and(bystatus);

        List<PurInPO> all = purInDao.findAll(new Specification<PurInPO>() {
            @Override
            public Predicate toPredicate(Root<PurInPO> root, CriteriaQuery<?> criteriaQuery,
                                         CriteriaBuilder cb) {
                Predicate predicate = null;

                if (!ValidateMember.isEmpty(purname)) {
                    Path<PurPO> purPO = root.get("purPO");
                    Predicate predicatepurname = cb.like(purPO.get("name").as(String.class), purname);
                    if (predicate == null) {
                        predicate = predicatepurname;
                    } else {
                        predicate = cb.and(predicate, predicatepurname);
                    }
                }

                if (!ValidateMember.isEmpty(inname)) {
                    Path<Object> purinname = root.get("name");
                    Predicate predicateinname = cb.like(purinname.as(String.class), inname);
                    if (predicate == null) {
                        predicate = predicateinname;
                    } else {
                        predicate = cb.and(predicate, predicateinname);
                    }
                }

                if (!ValidateMember.isEmpty(supplierid)) {
                    Path<SupplierPO> sup = root.get("purPO").get("supplierPO");
                    Predicate predicateinname = cb.equal(sup.get("id"), supplierid);
                    if (predicate == null) {
                        predicate = predicateinname;
                    } else {
                        predicate = cb.and(predicate, predicateinname);
                    }
                }

                if (!ValidateMember.isEmpty(statusId)) {
                    Path<Integer> status = root.get("status");
                    Predicate predicateinname = cb.equal(status, statusId);
                    if (predicate == null) {
                        predicate = predicateinname;
                    } else {
                        predicate = cb.and(predicate, predicateinname);
                    }
                }
                return predicate;
            }
        }, and);
        // 返回模糊查询结果
        return all;
    }

    // 02 根据 id查询
    public PurInPO findById(Long id) {
        return purInDao.findById(id).get();
    }

    // 03 查询排序 by 状态,定制日期
    public List<PurInPO> findAllsort() {

        Sort sortstatus = Sort.by(Direction.ASC, "status");

        Sort sortcreateTime = Sort.by(Direction.DESC, "createTime");
        Sort and = sortstatus.and(sortcreateTime);

        List<PurInPO> all = purInDao.findAll(and);
        return all;
    }

    // 保存菜单
    public PurInPO save(PurInPO purInPO) {
        return purInDao.save(purInPO);
    }

    // 删除菜单
    public void delete(PurInPO purInPO) {
        purInDao.delete(purInPO);
    }

    /**
     * 新建采购入库单 -- 包括明细
     */
    // 新建入库单 -- 入库单编制
    public AjaxResult newPurIn(PurInPO purInPO) {

        PurInPO save = new PurInPO();

        // 设定入库单号
        save.setName(UUIDUtile.engender("PIN"));

        // 设定仓管员
        save.setUserPO(purInPO.getUserPO());

        // 入库日期
        save.setCreateTime(new Date());

        // 入库单状态
        save.setStatus(PurInService.PURIN_STATUS_PRO_NO);

        // 上级的采购订单号
        PurPO purbyId = purchaseService.findById(purInPO.getPurPO().getId());
        save.setPurPO(purbyId);

        // purInPO 检测
        AjaxResult check = EntityCheckUtil.check(save);
        if (check.getCode() != 200) {
            return AjaxResult.fail(check.getCode(), check.getMsg());
        }

        // 保存父入库单
        save = purInService.save(save);

        // 上的明细
        save.setPurInDetailPOList(new ArrayList<PurInDetailPO>());
        for (PurInDetailPO purInDetailPO : purInPO.getPurInDetailPOList()) {
            GoodPO goodbyId = goodService.findById(purInDetailPO.getGoodPO().getId());
            PurInDetailPO p = new PurInDetailPO();
            p.setGoodPO(goodbyId);
            p.setGoodcount(purInDetailPO.getGoodcount());
            p.setPurInPO(save);
            PurInDetailPO savedetail = purInDetailService.save(p);
            save.getPurInDetailPOList().add(savedetail);
        }

        // 更新purinpo  执行库存更新
        save = purInService.save(save);
        HashMap<String, PurInPO> ret = new HashMap<>();
        ret.put("purInPO", save);

        if (save == null) {
            return AjaxResult.fail(500, "入库单保存失败");
        }

        return AjaxResult.success(200, "新建入库单", ret);
    }

    /**
     * 保存修改的入库单 /editpurin.ajax
     */
    public AjaxResult editpurinAjax(PurInPO purInPO) {

        PurInPO purInbyId = findById(purInPO.getId());

        List<PurInDetailPO> newInDetail = purInPO.getPurInDetailPOList();

        PurInDetailPO saveInDetail = null;

        for (PurInDetailPO purInDetailPO : newInDetail) {
            if (ValidateMember.isEmpty(purInDetailPO.getId())) { // 新添加
                PurInDetailPO newin = new PurInDetailPO();
                GoodPO goodbyId = goodService.findById(purInDetailPO.getGoodPO().getId());
                newin.setGoodPO(goodbyId);
                newin.setPurInPO(purInbyId);
                newin.setGoodcount(purInDetailPO.getGoodcount());
                saveInDetail = purInDetailService.save(newin);

            } else { // 老明细
                PurInDetailPO byId = purInDetailService.findById(purInDetailPO.getId());
                if (purInDetailPO.getGoodcount() == 0) { // 删除明细
                    purInDetailService.deleteById(byId.getId());
                } else { //  修改明细
                    byId.setGoodcount(purInDetailPO.getGoodcount());
                    saveInDetail = purInDetailService.save(byId);
                }
            }
        }

        purInbyId.setUpdateTime(new Date());
        PurInPO save = save(purInbyId);
        if (save != null) {
            return AjaxResult.success(200, save.getName() + ": 成功修改入库单", null);
        } else {
            return AjaxResult.fail(500, purInbyId.getName() + ": 修改失败");
        }


    }

    /**
     * 采购订单编辑页面 数据
     */
    public PurInPO editpurinDo(Long id) throws CloneNotSupportedException {
        // 获取采购入库单
        PurInPO purInbyId = purInService.findById(id);
        // clone返回列表
        PurInPO retpurin = (PurInPO) purInbyId.clone();

        // 重构 retpurin的 detaillist
        retpurin.setPurInDetailPOList(new ArrayList<PurInDetailPO>());
        for (PurInDetailPO purInDetailPO : purInbyId.getPurInDetailPOList()) {
            PurInDetailPO byId = purInDetailService.findById(purInDetailPO.getId());
            retpurin.getPurInDetailPOList().add(byId);
        }

        // 获取执行中的 采购订单
        PurPO purPO = purchaseService.findById(purInbyId.getPurPO().getId());

        // 采购订单中的明细
        List<PurDetailPO> purList = purPO.getPurDetailPOList();

        // 入库单中的明细
        List<PurInDetailPO> inList = purInbyId.getPurInDetailPOList();

        boolean flag = true;

        for (PurDetailPO purDetailPO : purList) {
            flag = true;
            purDetailPO = purDetailService.findById(purDetailPO.getId());

            for (PurInDetailPO purInDetailPO : inList) {
                purInDetailPO = purInDetailService.findById(purInDetailPO.getId());
         /* if (ValidateMember.isEmpty(purInDetailPO.getGoodcount())) {
            purInDetailPO.setGoodcount(0);
          }*/
                if (purDetailPO.getGoodPO().getId().longValue() == purInDetailPO.getGoodPO().getId()
                        .longValue()) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                PurInDetailPO newpurind = new PurInDetailPO();
                newpurind.setPurInPO(retpurin);
                newpurind.setGoodPO(purDetailPO.getGoodPO());
                newpurind.setGoodcount(0);
                newpurind.setPurInPO(purInbyId);
                retpurin.getPurInDetailPOList().add(newpurind);
            }
        }

        return retpurin;
    }

    /**
     * ajax 审核入库单
     *
     * @return
     */
    public AjaxResult auditPurInAjax(Long id, Integer status) {

        //0 编制
        //1 入库
        //3 废弃
        PurInPO purInbyId = null;

        Optional<PurInPO> byId = purInDao.findById(id);
        purInbyId = byId.isPresent() ? byId.get() : null;

        if (purInbyId == null) {
            return AjaxResult.fail(500, "没有查到相应记录: 订单Id为: " + id);
        }


        StockPO stockPO = purInbyId.getUserPO().getStockPO();

        // 状态不变
        if (purInbyId.getStatus() == status) {
            return AjaxResult.success(200, "状态 没有改变", null);
        }

        // 原状态0-编制, 现在status = 1 执行
        // 1 status = 1
        // 2 入库保存 -- instock(PurInPO purInbyId)
        if (purInbyId.getStatus() == 0 && status == 1) {

            AjaxResult ajaxResult = instockProc(purInbyId);
            if (ajaxResult.getCode() == 200) {
                purInbyId.setUpdateTime(new Date());
                purInbyId.setStatus(status);
                purInService.save(purInbyId);
            }

            return ajaxResult;
        }


        // 原状态0-编制, 现在status = 2
        // 1 status = 2
        if (purInbyId.getStatus() == 0 && status == 2) {

            purInbyId.setUpdateTime(new Date());
            purInbyId.setStatus(status);
            purInService.save(purInbyId);
            return AjaxResult.success(200, "成功操作,入库但废弃", null);
        }


        //  原状态1
        // 1 不允许 -- 已有入库记录
        if (purInbyId.getStatus() == 1) {
            return AjaxResult.success(200, "已有入库记录,不能执行", null);
        }


        //  原状态2 现在 0
        // 1 状态为0
        if (purInbyId.getStatus() == 2 && status == 0) {
            purInbyId.setUpdateTime(new Date());
            purInbyId.setStatus(status);
            purInService.save(purInbyId);

            return AjaxResult.success(200, "已重新启用", null);
        }

        //  原状态2 现在 1
        // 1 不允许 -- 先置于编制状态,确认后重新审核
        if (purInbyId.getStatus() == 2) {
            return AjaxResult.success(200, "请先重置到编制状态", null);
        }

        return AjaxResult.fail(500, "发生未知错误,请检查后台数据库");
    }

    // 查询已入库明细数量,供采购单使用
    public List<PurInPO> findAllByPurPO(PurPO pur) {

        return purInDao.findAllByPurPOAndStatus(pur, PurInService.PURIN_STATUS_ADMIN_NO);


    }

    private AjaxResult instockProc(PurInPO purin) {
        //  入库单回滚表
        ArrayList<RepoInfoPO> rbtable = new ArrayList<>();
        // 库存更新回滚表
        ArrayList<SummGoodPO> summGoodPOS = new ArrayList<>();

        // 仓库
        StockPO stockPO = purin.getUserPO().getStockPO();

        // 入库单明细
        List<PurInDetailPO> purInDetailPOList = purin.getPurInDetailPOList();
        for (PurInDetailPO detail : purInDetailPOList) {
            // 仓库和商品
            GoodPO goodPO = detail.getGoodPO();

            // 要更新的库存明细
            List<RepoInfoPO> item = repoInfoService.findAllByStockPOAndGoodPO(stockPO, goodPO);

            if (item == null || item.size() == 0) // 插入新条目
            {
                RepoInfoPO newRepoInfo = new RepoInfoPO();
                // 设定回滚时删除 数量0
                newRepoInfo.setGoodcount(0);
                newRepoInfo.setGoodspare(0);
                newRepoInfo.setThreshold(0);

                newRepoInfo.setGoodPO(goodPO);

                rbtable.add(newRepoInfo); // 保存回滚数据
                // insert
                newRepoInfo.setStockPO(stockPO);
                newRepoInfo.setGoodcount(detail.getGoodcount());
                newRepoInfo = repoInfoService.save(newRepoInfo);
                // 跟踪总库存
                SummGoodPO byGoodPO = summGoodService.findByGoodPO(goodPO);
                if (byGoodPO == null) {
                    SummGoodPO summGoodPO = new SummGoodPO();
                    summGoodPO.setGoodPO(goodPO);
                    summGoodPO.setGoodcount(detail.getGoodcount());
                    summGoodService.save(summGoodPO);
                } else {
                    byGoodPO.setGoodcount(byGoodPO.getGoodcount() + detail.getGoodcount());
                    summGoodService.save(byGoodPO);
                }


            } else {
                // 更新条目
                // 设定回滚时更新
                RepoInfoPO repoInfoPO = item.get(0);
                repoInfoPO.setGoodspare(0);
                repoInfoPO.setGoodPO(goodPO);
                rbtable.add(repoInfoPO); // 保存回滚数据
                // insert
                repoInfoPO.setGoodcount(detail.getGoodcount() + repoInfoPO.getGoodcount());
                repoInfoPO = repoInfoService.save(repoInfoPO);
                // 跟踪总库存
                SummGoodPO byGoodPO = summGoodService.findByGoodPO(goodPO);
                if (byGoodPO == null) {
                    SummGoodPO summGoodPO = new SummGoodPO();
                    summGoodPO.setGoodPO(goodPO);
                    summGoodPO.setGoodcount(detail.getGoodcount());
                    summGoodService.save(summGoodPO);
                } else {
                    byGoodPO.setGoodcount(byGoodPO.getGoodcount() + detail.getGoodcount());
                    summGoodService.save(byGoodPO);
                }
            }
        }

        return AjaxResult.success(200, "成功更新库存", null);
    }

}
